<template xmlns:v-dinput="http://www.w3.org/1999/xhtml">
  <div id="app">
    <div class="page_top">
      <div>
        下载位置: {{ outpath }}
        <button @click="clear_query">
          重新抓取
        </button>
      </div>
      <div>
        抓取单词: <input type="text" v-model="word" />
        <button @click="begin_query(false, word)">
          开始抓取
        </button>
        <button @click="xunhuan_query">
          文件循环抓取
        </button>
        <button @click="stop_action">
          停止抓取
        </button>
        <button
          @click="
            canPlayAudio(
              'http://tts.iciba.com/output/EN_Female1/2/71/c2b9392afab55db49231e047e6108.mp3'
            )
          "
        >
          单词
        </button>
      </div>
      <div>
        <span class="status_span">第{{ currindex + 1 }}个单词</span>
        <span class="status_span">第{{ bookIndex + 1 }}本书</span>
        上传状态：<span>{{ status }}</span>
      </div>
    </div>
    <div class="page_bottom">
      <textarea
        name=""
        id=""
        cols="30"
        rows="10"
        :value="word_his_arr.join('\n')"
      ></textarea>
    </div>
  </div>
</template>

<script>
import pLimit from 'p-limit'
const request = require('request')
const fs = window.require('fs')
let readline = window.require('readline')
const FormData = require('form-data')
const path = require('path')
// const { app } = window.require("electron").remote;
const md5 = require('md5')

export default {
  name: 'App',
  data: function() {
    return {
      word: 'good',
      currindex: -1,
      status: '',
      outpath: '',
      shangchuan: 'http://192.168.3.42:9898/api/oss/uploadByURL',
      tijiao: 'http://192.168.3.42:9898/api/getWordByPoolA',
      qianzhi: 'http://192.168.3.42:9898/api/getWordIsExit',
      apiaddress: 'http://schoolapitest.xhkjedu.com',
      uploadaddress: 'http://schoolfiletest.xhkjedu.com',
      downloadaddress: 'http://schoolfiletest.xhkjedu.com',
      wordlist: [],
      wordresult: {
        word_name: '',
        word_pl: '',
        word_er: '',
        word_est: '',
        ph_en: '',
        ph_am: '',
        ph_en_mp3: '',
        ph_am_mp3: '',
        mean_all: '',
        wordtypeList: [],
        wordphraseList: [],
        wordexamList: [],
        wordexampleList: [],
        download_num: 0,
        jscbMessage: {}
      },
      upload_arr: [],
      word_his_arr: [],
      isstop: false,
      jieshu: false,
      rightShangchuan: true,
      xianzhi: 0,
      bookList: [
        {
          name: 'CET4luan_1'
        },
        {
          name: 'CET6luan_1'
        },
        {
          name: 'KaoYanluan_1'
        },
        {
          name: 'Level4luan_1'
        },
        {
          name: 'Level8_1'
        },
        {
          name: 'CET4luan_2'
        },
        {
          name: 'CET6_2'
        },
        {
          name: 'KaoYan_2'
        },
        {
          name: 'Level4luan_2'
        },
        {
          name: 'Level8luan_2'
        },
        {
          name: 'CET4_3'
        },
        {
          name: 'CET6_3'
        },
        {
          name: 'KaoYan_3'
        },
        {
          name: 'CET4_1'
        },
        {
          name: 'CET6_1'
        },
        {
          name: 'KaoYan_1'
        },
        {
          name: 'Level4_1'
        },
        {
          name: 'CET4_2'
        },
        {
          name: 'Level4_2'
        },
        {
          name: 'Level8_2'
        },
        {
          name: 'IELTSluan_2'
        },
        {
          name: 'TOEFL_2'
        },
        {
          name: 'GRE_2'
        },
        {
          name: 'SAT_2'
        },
        {
          name: 'GMATluan_2'
        },
        {
          name: 'IELTS_3'
        },
        {
          name: 'TOEFL_3'
        },
        {
          name: 'GRE_3'
        },
        {
          name: 'SAT_3'
        },
        {
          name: 'GMAT_3'
        },
        {
          name: 'IELTS_2'
        },
        {
          name: 'GMAT_2'
        },
        {
          name: 'ChuZhongluan_2'
        },
        {
          name: 'GaoZhongluan_2'
        },
        {
          name: 'ChuZhong_3'
        },
        {
          name: 'GaoZhong_3'
        },
        {
          name: 'PEPXiaoXue3_1'
        },
        {
          name: 'PEPXiaoXue3_2'
        },
        {
          name: 'PEPXiaoXue4_1'
        },
        {
          name: 'PEPXiaoXue4_2'
        },
        {
          name: 'PEPXiaoXue5_1'
        },
        {
          name: 'PEPXiaoXue5_2'
        },
        {
          name: 'PEPXiaoXue6_1'
        },
        {
          name: 'PEPXiaoXue6_2'
        },
        {
          name: 'PEPChuZhong7_1'
        },
        {
          name: 'PEPChuZhong7_2'
        },
        {
          name: 'PEPChuZhong8_1'
        },
        {
          name: 'PEPChuZhong8_2'
        },
        {
          name: 'PEPChuZhong9_1'
        },
        {
          name: 'WaiYanSheChuZhong_1'
        },
        {
          name: 'WaiYanSheChuZhong_2'
        },
        {
          name: 'WaiYanSheChuZhong_3'
        },
        {
          name: 'WaiYanSheChuZhong_4'
        },
        {
          name: 'WaiYanSheChuZhong_5'
        },
        {
          name: 'WaiYanSheChuZhong_6'
        },
        {
          name: 'PEPGaoZhong_1'
        },
        {
          name: 'PEPGaoZhong_2'
        },
        {
          name: 'PEPGaoZhong_3'
        },
        {
          name: 'PEPGaoZhong_4'
        },
        {
          name: 'PEPGaoZhong_5'
        },
        {
          name: 'PEPGaoZhong_6'
        },
        {
          name: 'PEPGaoZhong_7'
        },
        {
          name: 'PEPGaoZhong_8'
        },
        {
          name: 'PEPGaoZhong_9'
        },
        {
          name: 'PEPGaoZhong_10'
        },
        {
          name: 'PEPGaoZhong_11'
        },
        {
          name: 'ChuZhong_2'
        },
        {
          name: 'GaoZhong_2'
        },
        {
          name: 'BEC_2'
        },
        {
          name: 'BEC_3'
        },
        {
          name: 'BeiShiGaoZhong_1'
        },
        {
          name: 'BeiShiGaoZhong_2'
        },
        {
          name: 'BeiShiGaoZhong_3'
        },
        {
          name: 'BeiShiGaoZhong_4'
        },
        {
          name: 'BeiShiGaoZhong_5'
        },
        {
          name: 'BeiShiGaoZhong_6'
        },
        {
          name: 'BeiShiGaoZhong_7'
        },
        {
          name: 'BeiShiGaoZhong_8'
        },
        {
          name: 'BeiShiGaoZhong_9'
        },
        {
          name: 'BeiShiGaoZhong_10'
        },
        {
          name: 'BeiShiGaoZhong_11'
        }
      ],
      bookIndex: 78,
      huanshu: true,
      zanting: true
    }
  },
  components: {},
  mounted() {
    console.info(process.cwd())
    this.outpath = path.join('D:/', 'LinShiWenJianXiaZaiWeiZhi') // 这里是 E 盘的路径
    fs.mkdir(this.outpath, () => {})
    this.word = window.localStorage.getItem('word') || ''
    this.currindex = parseInt(window.localStorage.getItem('currindex') || 0)
    if (this.currindex !== 0) {
      this.currindex = this.currindex + 1
    }
    // this.readfile();
  },
  watch: {
    // 监听并发任务数量
    xianzhi(newVal) {
      if (newVal < 6 && this.huanshu === false && this.zanting) {
        // 当并发数量小于限制时，继续执行任务
        let randomDelay = Math.random() * 1000 // 0 到 1000 毫秒
        // setTimeout(() => {
        this.kaishi()
        // }, randomDelay)
      }
    }
  },
  methods: {
    clear_query() {
      this.word = ''
      this.currindex = 0
      this.word_his_arr = []
      window.localStorage.setItem('word', this.word)
      window.localStorage.setItem('currindex', this.currindex)
      // this.readfile()
    },
    //创建上传后端数据流
    reset() {
      this.wordresult.word_name = ''
      this.wordresult.word_pl = ''
      this.wordresult.word_er = ''
      this.wordresult.word_est = ''
      this.wordresult.ph_en = ''
      this.wordresult.ph_am = ''
      this.wordresult.ph_en_mp3 = ''
      this.wordresult.ph_am_mp3 = ''
      this.wordresult.mean_all = ''
      this.wordresult.wordtypeList = []
      this.wordresult.wordphraseList = []
      this.wordresult.wordexamList = []
      this.wordresult.wordexampleList = []

      this.upload_arr = []
    },
    //停止抓取
    stop_action() {
      this.zanting = false
      this.isstop = true
    },
    mget: function(url, para) {
      let parastr = ''
      for (let key in para) {
        parastr += '&' + key + '=' + para[key]
      }
      parastr = parastr.slice(1, parastr.length)
      url = url + '?' + parastr
      return new Promise(function(resolve, reject) {
        request(
          {
            url: url,
            method: 'get',
            json: true,
            headers: {
              'content-type': 'application/json'
            }
          },
          function(error, response, body) {
            if (!error && response.statusCode === 200) {
              resolve(body)
            } else {
              reject('请求接口失败')
            }
          }
        )
      })
    },
    mpost: function(url, para) {
      return new Promise(function(resolve, reject) {
        request(
          {
            url: url,
            method: 'POST',
            json: true,
            headers: {
              'content-type': 'application/json'
            },
            body: para
          },
          function(error, response, body) {
            if (!error && response.statusCode === 200) {
              resolve(body)
            } else {
              reject('请求接口失败')
            }
          }
        )
      })
    },
    down_action(fileurl, filename, callback) {
      let filepath = this.outpath + '\\' + filename
      let stream = fs.createWriteStream(filepath)
      request(fileurl)
        .pipe(stream)
        .on('close', function(error) {
          if (!error) {
            // console.log("文件[" + filename + "]下载完毕");
            callback(filename)
          }
        })
    },
    uploadques_action: function(filename, callback) {
      let that = this
      let filepath = this.outpath + '\\' + filename
      fs.readFile(filepath, (err, data) => {
        if (!err) {
          let file = new File([data], filename, {
            type: 'image/' + filename.split('.').reverse()[0]
          })
          let form = new FormData()
          form.append('file', file)
          form.append('savefolder', 'cidian')
          form.append('iscover', 1)
          form.append('isrename', 0)
          let request_url = that.uploadaddress + '/up/upfile2'
          let xhr = new XMLHttpRequest()
          xhr.open('post', request_url)
          xhr.send(form)
          xhr.onload = function() {
            callback(this.responseText)
            if (fs.existsSync(filepath)) {
              fs.unlinkSync(filepath)
            }
          }
        }
      })
    },
    dateFormat: function(fmt, date) {
      let ret
      const opt = {
        'Y+': date.getFullYear().toString(), // 年
        'm+': (date.getMonth() + 1).toString(), // 月
        'd+': date.getDate().toString(), // 日
        'H+': date.getHours().toString(), // 时
        'M+': date.getMinutes().toString(), // 分
        'S+': date.getSeconds().toString() // 秒
      }
      for (let k in opt) {
        ret = new RegExp('(' + k + ')').exec(fmt)
        if (ret) {
          fmt = fmt.replace(
            ret[1],
            ret[1].length === 1 ? opt[k] : opt[k].padStart(ret[1].length, '0')
          )
        }
      }
      return fmt
    },
    readFileToArr(fReadName, callback) {
      let fRead = fs.createReadStream(fReadName)
      let objReadline = readline.createInterface({
        input: fRead
      })
      let arr = []
      objReadline.on('line', function(line) {
        arr.push(line)
      })
      objReadline.on('close', function() {
        callback(arr)
      })
    },
    async readfile() {
      let that = this
      try {
        //选书
        const response = await fetch(
          `/${that.bookList[that.bookIndex].name}.json`
        )
        if (!response.ok) {
          throw new Error('网络响应不正常')
        }
        // 解析 JSON 数据
        let data = await response.json()
        that.wordlist = data.map((item) => item.headWord)
        // that.word = that.wordlist[that.currindex]
        that.currindex = -1
        that.huanshu = false
      } catch (error) {
        console.error('加载 JSON 数据时出错:', that.bookList[that.bookIndex].name)
      }
    },
    //抓取
    async xunhuan_query() {
      await this.readfile()
      await this.kaishi()
    },
    //快速启动
    async kaishi() {
      if (this.jieshu === false) {
        this.currindex++ // 正确的自增操作
        this.xianzhi++
        if (this.currindex < this.wordlist.length) {
          this.word = this.wordlist[this.currindex]
          this.begin_query(true, this.wordlist[this.currindex])
        } else {
          if (this.bookIndex + 1 > this.bookList.length) {
            this.jieshu = true
            console.log('结束啦')
          } else {
            this.bookIndex++
            this.huanshu = true
            console.log('下一本', this.bookIndex)
            this.xunhuan_query()
          }
        }
      }
    },
    begin_query(v, word) {
      // console.log("开始");
      this.isstop = false
      this.cidian_query(v, word)
    },
    //抓取 限制
    //开始抓取
    async cidian_query(v, word) {
      this.status = ''
      const statusObj = this.bookIndex + 1
      // if (this.isstop) {
      //   return
      // }
      try {
        let openUrl =
          this.qianzhi +
          `?timestamp=${Math.floor(100000 + Math.random() * 900000)}`
        const data = {
          word: word,
          englishId: statusObj
        }
        const qian = await this.mpost(openUrl, data)
        if (qian.data) {
          if (v !== false) {
            this.xianzhi--
          }
          // this.currindex++
        } else {
          try {
            this.reset()
            // const word = this.word
            let u = {
              client: 6,
              key: 1000006,
              timestamp: new Date().valueOf(),
              word: word
            }
            let i = 'http://dict.iciba.com/dictionary/word/query/web'
            let l = ''
            for (let c in u) {
              l += String(u[c])
            }
            u.signature = md5(
              i.replace('http://dict.iciba.com', '') +
                l +
                '7ece94d9f9c202b0d2ec557dg4r9bc'
            )
            const obj = await this.mget(i, u)
            if (obj.status === 1) {
              const objectData = obj.message
              const limit = pLimit(6)
              // 处理 baesInfo.symbols
              if (
                objectData.baesInfo &&
                objectData.baesInfo.symbols &&
                this.rightShangchuan
              ) {
                // for (let item of objectData.baesInfo.symbols) {
                //   try {
                //     // 逐个文件上传
                //     item.ph_en_mp3 = await this.openOss(item.ph_en_mp3)
                //     item.ph_en_mp3_bk = await this.openOss(item.ph_en_mp3_bk)
                //     item.ph_tts_mp3 = await this.openOss(item.ph_tts_mp3)
                //     item.ph_tts_mp3_bk = await this.openOss(item.ph_tts_mp3_bk)
                //     item.ph_am_mp3 = await this.openOss(item.ph_am_mp3)
                //     item.ph_am_mp3_bk = await this.openOss(item.ph_am_mp3_bk)
                //   } catch (error) {
                //     console.error('上传文件时出错:', error)
                //   }
                // }
                try {
                  await Promise.all(
                    objectData.baesInfo.symbols.map((item) =>
                      limit(async () => {
                        item.ph_en_mp3 = await this.openOss(item.ph_en_mp3)
                        item.ph_en_mp3_bk = await this.openOss(
                          item.ph_en_mp3_bk
                        )
                        item.ph_tts_mp3 = await this.openOss(item.ph_tts_mp3)
                        item.ph_tts_mp3_bk = await this.openOss(
                          item.ph_tts_mp3_bk
                        )
                        item.ph_am_mp3 = await this.openOss(item.ph_am_mp3)
                        item.ph_am_mp3_bk = await this.openOss(
                          item.ph_am_mp3_bk
                        )
                      })
                    )
                  )
                } catch (error) {
                  console.error('上传文件时出错:', error)
                }
              }
              // 处理 collins
              if (objectData.collins && this.rightShangchuan) {
                for (let collin of objectData.collins) {
                  for (let entry of collin.entry) {
                    try {
                      await Promise.all(
                        entry.example.map((item) =>
                          limit(async () => {
                            item.tts_mp3 = await this.openOss(item.tts_mp3)
                          })
                        )
                      )
                    } catch (error) {
                      console.error('上传音频失败:', error)
                    }
                    // for (let example of entry.example) {
                    //   try {
                    //     example.tts_mp3 = await this.openOss(example.tts_mp3)
                    //   } catch (error) {
                    //     console.error('上传音频失败:', error)
                    //   }
                    // }
                  }
                }
              }
              // 处理 new_sentence
              if (objectData.new_sentence && this.rightShangchuan) {
                for (let sentenceObj of objectData.new_sentence) {
                  try {
                    await Promise.all(
                      sentenceObj.sentences.map((item) =>
                        limit(async () => {
                          item.ttsUrl = await this.openOss(item.ttsUrl)
                        })
                      )
                    )
                  } catch (error) {
                    console.error('上传音频失败:', error)
                  }
                  // for (let sentence of sentenceObj.sentences) {
                  //   try {
                  //     sentence.ttsUrl = await this.openOss(sentence.ttsUrl)
                  //   } catch (error) {
                  //     console.error('处理 new_sentence 时出错:', error)
                  //   }
                  // }
                }
              }
              let openUrl =
                this.tijiao +
                `?timestamp=${Math.floor(100000 + Math.random() * 900000)}`
              const data = {
                message: objectData,
                status: statusObj
              }
              this.mpost(openUrl, data).then((res) => {
                // console.log('123',res.data === 'ok');
                if (res.data === 'ok') {
                  // console.log(objectData.baesInfo.word_name, ':上传完成')
                  if (v !== false) {
                    this.xianzhi--
                  }
                } else {
                  console.log('书名：', this.bookList[this.bookIndex].name)
                  console.log('第', this.currindex + 1, '个')
                  console.log(word, ':上传失败')
                  if (v !== false) {
                    this.xianzhi--
                  }
                }
              })
            }
          } catch (e) {
            console.info(e)
          }
        }
      } catch (error) {
        console.info(error)
      }
    },
    // canPlayAudio(url) {
    //   const audio = new Audio(url)
    //   return new Promise((resolve) => {
    //     audio.oncanplay = () => {
    //       resolve(true)
    //       audio.remove()
    //     }
    //     audio.onerror = () => {
    //       resolve(false)
    //       audio.remove()
    //     }
    //   })
    // },
    async canPlayAudio(url) {
      try {
        const response = await fetch(url, { method: 'HEAD' }) // 只请求头信息
        return response.ok // 如果状态码是 200-299，返回 true，否则返回 false
      } catch (error) {
        return false // 如果请求失败，比如网络错误，返回 false
      }
    },
    async processData(data) {
      await this.openOss(data)
    },
    //上传oss
    async openOss(url) {
      if (!url || url.trim() === '') {
        console.log('URL为空，跳过上传:', url)
        return null // 如果URL为空，返回null，不影响后续操作
      }
      try {
        // 检查音频是否可以播放
        let result = await this.canPlayAudio(url)
        if (result) {
          let openUrl =
            this.shangchuan +
            `?timestamp=${Math.floor(100000 + Math.random() * 900000)}`
          let mp3Url = { url: url, type: 'english_MVP/wordMp3_message/' }
          // 等待网络请求返回CET4luan_1
          let res = await this.mpost(openUrl, mp3Url)
          // 确保返回的是字符串，如果没有数据返回，使用默认值
          return res.data || '' // 如果没有返回数据，返回默认值
        } else {
          console.log('音频不可以播放，返回原始 URL:', url)
          return url // 返回原来的 URL
        }
      } catch (err) {
        console.log('处理音频时出错:', err)
      }
    },
    //下载
    cidian_upload() {
      let upload_arr = this.upload_arr
      let uploadcount = 0
      // console.log("进入", this.upload_arr);
      if (upload_arr.length === 0) {
        this.status = '上传完成'
        this.uploadapi()
      } else {
        for (let i = 0; i < upload_arr.length; i++) {
          let fileurl = upload_arr[i]
          let filename = fileurl
            .split('/')
            .slice(3)
            .join('/')
          filename = filename.replace(/\//g, '_')
          this.down_action(fileurl, filename, (filename) => {
            this.uploadques_action(filename, () => {
              uploadcount += 1
              this.status = uploadcount + '/' + upload_arr.length
              if (uploadcount === upload_arr.length) {
                this.status = '上传完成'
                this.uploadapi()
              }
            })
          })
        }
      }
    },
    //最终上传
    uploadapi() {
      let that = this
      let url = this.apiaddress + '/word/save'
      this.mpost(url, this.wordresult)
        .then(() => {
          window.localStorage.setItem('word', that.word)
          window.localStorage.setItem('currindex', that.currindex)
          that.word_his_arr.push(that.word)
          that.currindex = that.currindex + 1
          let wordlist = that.wordlist

          if (that.currindex < wordlist.length) {
            that.word = wordlist[that.currindex]
            // 生成一个 0 到 500 毫秒之间的随机延时
            let randomDelay = Math.random() * 500 // 0 到 500 毫秒
            setTimeout(() => {
              that.cidian_query()
            }, randomDelay)
          }
        })
        .catch(() => {})
    }
  }
}
</script>

<style lang="less">
body {
  margin: 0;
  padding: 0;
}

.hidden {
  visibility: hidden;
}

button {
  margin-left: 10px;
}

textarea {
  font-size: 18px;
}

.line {
  border-bottom: 1px solid darkslategrey;
  margin-top: 10px;
  margin-bottom: 10px;
}

#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  margin: 0;
  padding: 0;
  color: #2c3e50;
  background: #f3f3f3;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.status_span {
  margin-right: 20px;
}

.page_top {
  display: flex;
  flex-direction: column;
  flex: none;

  > div {
    display: flex;
    padding-left: 10px;
    padding-right: 10px;
    margin-top: 10px;

    > input {
      flex: auto;
      margin-left: 10px;
    }
  }
}

.page_bottom {
  flex: auto;
  display: flex;
  margin-top: 10px;
  margin-bottom: 10px;
  justify-content: center;

  textarea {
    width: calc(100% - 20px);
  }
}
</style>
